import * as fs from 'fs';
import * as path from 'path';
import PNG from 'pngjs';
import { spawn } from 'child_process';
import pLimit from 'p-limit';
import os from 'os';
import chalk from 'chalk';

const PROJECT_ROOT = path.resolve(__dirname, '../..');

// 获取当前执行文件的目录
const pngquantPath = path.join(PROJECT_ROOT, "pngquant.exe");

// 并发控制器（根据CPU核心数自动设置）
const limit = pLimit(os.cpus().length);

// 包装压缩操作为Promise
async function compressFile(filePath: string): Promise<string> {
    return new Promise((resolve, reject) => {
        const args = [
            // '--verbose',
            '-f',
            '--ext', '.png',
            '--quality', '70-80',
            filePath,
        ];
        // console.debug('执行命令:', `${pngquantPath} ${args.join(' ')}`);
        const child = spawn(pngquantPath, args, {
            stdio: 'inherit'
        });

        child.stderr?.on('data', (data) => {
            console.error(`stderr: ${data}`);
        });

        child.on('close', (code) => {
            if (code === 0) {
                resolve(filePath);
            } else {
                reject(new Error(`压缩失败，退出码: ${code} (${filePath})`));
            }
        });

    });
}

export async function compressOrigin(dir: string): Promise<string[]> {
    const pngFiles: string[] = [];

    console.log(`检查压缩目录 => ${dir}`);

    // 递归遍历目录函数
    const walkDir = (currentDir: string) => {
        const files = fs.readdirSync(currentDir);
        for (const file of files) {
            const filePath = path.join(currentDir, file);
            const stat = fs.statSync(filePath);

            if (stat.isDirectory()) {
                walkDir(filePath);
            } else if (path.extname(file).toLowerCase() === '.png') {
                // 检查PNG模式
                try {
                    const buffer = fs.readFileSync(filePath);
                    const png = PNG.PNG.sync.read(buffer);
                    if (!png.palette) { // 仅处理非调色板模式
                        pngFiles.push(filePath);
                    }
                } catch (err) {
                    console.error(chalk.red(`读取失败: ${filePath}`, err));
                }
            }
        }
    }

    // 开始遍历
    walkDir(path.resolve(dir));

    console.log(`发现 ${pngFiles.length} 个待压缩文件`);

    // 创建并发任务队列
    const tasks = pngFiles.map(filePath =>
        limit(async () => {
            try {
                console.log(`开始压缩: ${path.basename(filePath)}`);
                await compressFile(filePath);
                console.log(chalk.green(`压缩完成: ${path.basename(filePath)}`));
                return filePath;
            } catch (err) {
                if (err instanceof Error) {
                    console.error(chalk.red(`压缩失败: ${path.basename(filePath)}`, err.message));
                } else {
                    console.error(chalk.red(`压缩失败: ${path.basename(filePath)}`, String(err)));
                }
                return null;
            }
        })
    );

    // 等待所有任务完成
    const results = await Promise.all(tasks);

    // 过滤失败项
    const successFiles = results.filter(Boolean) as string[];
    console.log(`完成 ${successFiles.length}/${pngFiles.length} 个文件压缩`);
    return successFiles;
}

// 命令行入口
if (require.main === module) {
    const args = process.argv.slice(2);
    if (args.length < 1) {
        console.error("x 请输入需要压缩的目录");
        process.exit(1);
    }

    const targetDir = path.resolve(args[0]);
    console.log(`启动压缩任务: ${targetDir}`);

    compressOrigin(targetDir)
        .then(() => process.exit(0))
        .catch(err => {
            console.error(' 全局捕获错误:', err);
            process.exit(1);
        });
}
